﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;

namespace 数据库常用操作封装
{
    public class AccessDB
    {
        private OleDbConnection connection; // 数据库连接对象
        private string connectionString; // 连接字符串
        public OleDbConnection Connection { get => connection; set => connection = value; }
        public string ConnectionString { get => connectionString; set => connectionString = value; }
        /// <summary>
        /// 构造函数，传入数据库文件路径
        /// </summary>
        /// <param name="filePath">数据库文件路径</param>
        public AccessDB(string filePath)
        {
            Initialize(filePath);
        }
        /// <summary>
        /// 设置连接字符串并打开数据库连接
        /// </summary>
        /// <param name="connectionString">新的连接字符串。</param>
        public void SetConnectionString(string connectionString)
        {
            this.connectionString = connectionString;

            try
            {
                if (connection != null)
                {
                    connection.Close();
                }

                connection = new OleDbConnection(connectionString);
                connection.Open();
            }
            catch (Exception ex)
            {
                throw new Exception("连接数据库失败：" + ex.Message, ex);
            }
        }
        /// <summary>
        /// 初始化方法，根据数据库文件路径创建连接字符串并打开数据库连接
        /// </summary>
        /// <param name="filePath">数据库文件路径</param>
        private void Initialize(string filePath)
        {
            OleDbConnectionStringBuilder builder = new OleDbConnectionStringBuilder();
            builder.DataSource = filePath;
            builder.Provider = "Microsoft.Jet.OLEDB.4.0";
            builder.PersistSecurityInfo = false;
            connectionString = builder.ConnectionString;

            try
            {
                connection = new OleDbConnection(connectionString);
                connection.Open();
            }
            catch (Exception ex)
            {
                throw new Exception("连接数据库失败：" + ex.Message, ex);
            }
        }

        /// <summary>
        /// 断开连接方法，关闭连接并释放连接对象占用的资源
        /// </summary>
        public void Disconnect()
        {
            if (connection != null) // 判断连接对象是否为空
            {
                connection.Close(); // 关闭连接
                connection.Dispose(); // 释放连接对象所占用的资源
                connection = null; // 将连接对象设置为 null，表示已断开连接
            }
        }

        /// <summary>
        /// 执行查询方法，传入 SQL 查询语句
        /// </summary>
        /// <param name="query">SQL 查询语句</param>
        /// <returns>返回 OleDbDataReader 数据读取器对象</returns>
        public OleDbDataReader ExecuteQuery(string query)
        {
            using (OleDbCommand command = new OleDbCommand(query, connection))
            {
                try
                {
                    return command.ExecuteReader(); // 执行 SQL 查询语句并返回数据读取器对象
                }
                catch (Exception ex)
                {
                    throw new Exception("执行 SQL 查询语句失败：" + ex.Message, ex);
                }
            }
        }

        /// <summary>
        /// 执行非查询方法，传入 SQL 语句
        /// </summary>
        /// <param name="query">SQL 语句</param>
        /// <returns>返回受影响的行数</returns>
        public int ExecuteNonQuery(string query)
        {
            using (OleDbCommand command = new OleDbCommand(query, connection))
            {
                try
                {
                    return command.ExecuteNonQuery(); // 执行 SQL 语句并返回受影响的行数
                }
                catch (Exception ex)
                {
                    throw new Exception("执行 SQL 语句失败：" + ex.Message, ex);
                }
            }
        }

        /// <summary>
        /// 获取指定表中某字段的行数
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="fieldName">字段名</param>
        /// <returns>返回行数</returns>
        public int GetRowCount(string tableName, string fieldName)
        {
            string query = string.Format("SELECT COUNT(*) FROM {0} WHERE {1} IS NOT NULL", tableName, fieldName);

            using (OleDbCommand command = new OleDbCommand(query, connection))
            {
                try
                {
                    return (int)command.ExecuteScalar(); // 执行 SQL 查询语句并返回结果集的第一行第一列的值（即行数）
                }
                catch (Exception ex)
                {
                    throw new Exception("获取行数失败：" + ex.Message, ex);
                }
            }
        }

        /// <summary>
        /// 获取指定表的行数
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <returns>返回行数</returns>
        public int GetTableRowCount(string tableName)
        {
            // 构造查询语句，用COUNT函数统计表记录总数
            string query = string.Format("SELECT COUNT(*) FROM {0}", tableName);

            using (OleDbCommand command = new OleDbCommand(query, connection))
            {
                try
                {
                    // 执行 SQL 查询语句并返回结果集的第一行第一列的值（即行数）
                    return (int)command.ExecuteScalar();
                }
                catch (Exception ex)
                {
                    // 如果发生异常，抛出一个新异常，包含错误消息和原始异常
                    throw new Exception("获取行数失败：" + ex.Message, ex);
                }
            }
        }
        /// <summary>
        /// 查询指定表格中的一列数据，返回一个泛型集合
        /// </summary>
        /// <param name="tableName">要查询的表格名称</param>
        /// <param name="columnName">要查询的列名称</param>
        /// <returns>包含查询结果的泛型列表</returns>
        public List<string> GetColumnData(string tableName, string columnName)
        {
            var result = new List<string>();
            var command = new OleDbCommand($"SELECT [{columnName}] FROM [{tableName}]", connection);
            var reader = command.ExecuteReader();
            while (reader.Read())
            {
                result.Add(reader[columnName].ToString());
            }
            return result;
        }
        /// <summary>
        /// 获取 Access 数据库中所有表格名称
        /// </summary>
        /// <returns>包含所有表格名称的列表</returns>
        public List<string> GetAllTableNames()
        {
            var result = new List<string>();  // 创建一个泛型列表用于存储查询结果

            var schema = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);  // 获取 Tables 元数据信息
            foreach (DataRow row in schema.Rows)  // 遍历每一行元数据信息
            {
                string tableName = row["TABLE_NAME"].ToString().Trim();  // 获取当前行的表格名称
                if (!tableName.StartsWith("MSys"))  // 如果该表格不是系统表格
                {
                    result.Add(tableName);  // 将表格名称加入到结果列表中
                }
            }
            return result;  // 返回查询结果
        }
        public static void WriteToAccess(string connectionString, string tableName, string[] fieldNames, object[] values)
        {
            using (OleDbConnection connection = new OleDbConnection(connectionString)) // 创建连接对象并打开数据库连接（using语句确保在方法结束时自动释放资源）
            {
                string query = "INSERT INTO " + tableName + "("; // 定义插入数据的SQL查询语句
                for (int i = 0; i < fieldNames.Length; i++) // 循环遍历所有要插入的字段名
                {
                    query += fieldNames[i]; // 将字段名添加到SQL查询语句中
                    if (i != fieldNames.Length - 1) // 判断是否为最后一个字段名
                    {
                        query += ", "; // 如果不是最后一个字段名，在字段名之间加上逗号
                    }
                }
                query += ") VALUES ("; // 在SQL查询语句中添加"VALUES ("字符串

                for (int i = 0; i < values.Length; i++) // 循环遍历所有要插入的值
                {
                    if (values[i] is string) // 判断值的类型是否为字符串
                    {
                        query += "'" + values[i] + "'"; // 如果是字符串，在值两侧添加引号
                    }
                    else
                    {
                        query += values[i].ToString(); // 如果不是字符串，直接添加值
                    }

                    if (i != values.Length - 1) // 判断是否为最后一个值
                    {
                        query += ", "; // 如果不是最后一个值，在值之间加上逗号
                    }
                }
                query += ")"; // 在SQL查询语句中添加")"字符串

                using (OleDbCommand command = new OleDbCommand(query, connection)) // 创建命令对象，并使用SQL查询语句和连接对象进行初始化
                {
                    connection.Open(); // 打开数据库连接
                    command.ExecuteNonQuery(); // 执行插入操作，将数据写入Access数据库
                }
            }
        }
    }
}